﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Data;
using System.Data.SqlClient;


namespace RISMOTAXDP.EmailService
{
    /// <summary>
    /// 邮件接收及发送线程
    /// </summary>
    public class MailTransferThread : IDisposable
    {

        /// <summary>
        /// 线程对象
        /// </summary>
        private Thread m_Thread;

        /// <summary>
        /// 邮件发送处理对象
        /// </summary>
        private MailTransfer.MailSender m_Sender;

        /// <summary>
        /// 初始化
        /// </summary>
        public MailTransferThread()
        {
            //1、生成邮件发送子程序
            m_Sender = new MailTransfer.MailSender();

            //2、创建线程
            m_Thread = new Thread(new ThreadStart(ThreadRun));
        }


        /// <summary>
        /// 启动线程
        /// </summary>
        public void Start()
        {
            //1、启动线程
            if (State == ThreadState.Stopped)
            {
                m_Thread = new Thread(new ThreadStart(ThreadRun));
            }
            if (State == ThreadState.Unstarted)
            {
                m_Thread.Start();
            }
        }

        /// <summary>
        /// 停止线程
        /// </summary>
        public void Stop()
        {
            //1、停止线程
            try
            {
                m_Thread.Interrupt();
                if (m_Thread.ThreadState != ThreadState.Stopped)
                {
                    m_Thread.Join();
                }
            }
            catch { }
        }

        private void ThreadRun()
        {
            while (true)
            {
                bool mailAllSend = true;

                //检查系统执行状态

                if (GlobalObject.State == ServiceState.Stopped)
                {
                    break;
                }

                switch (GlobalObject.State)
                {
                    case ServiceState.Stopped: //停止
                        break;
                    case ServiceState.Running: //运行
                        //创建数据库连接
                        //break;
                        SqlConnection conn = GlobalObject.CreateConnect();
                        if (conn != null)
                        {
                            if (mailAllSend || GlobalObject.SystemInfo.MailCheckInterval <= GlobalObject.SystemInfo.MailTransferInterval)
                            {
                                if (CanContinue(conn))
                                {

                                    try
                                    {   //检查待发送邮件
                                        m_Sender.CheckData(conn, GlobalObject.DataBaseInfo.MailServerList);
                                    }
                                    catch (Exception ex)
                                    {
                                        GlobalObject.WriteOperationLog("E83000001", ex);
                                    }
                                }
                                mailAllSend = true;

                                //发送待发送邮件（执行发送邮件处理）
                                foreach (MailServerInfo mailServer in m_Sender.ServerList)
                                {
                                    if (!CanContinue(conn)) break;
                                    int sendMailCount = m_Sender.GetMailCount(mailServer);
                                    if (sendMailCount == 0)
                                    {
                                        break;
                                    }
                                    else if (GlobalObject.SystemInfo.MailTransferLimit != 0 && sendMailCount > GlobalObject.SystemInfo.MailTransferLimit)
                                    {
                                        sendMailCount = GlobalObject.SystemInfo.MailTransferLimit;
                                    }
                                    //尝试计次
                                    int tryTimes = 1;
                                    //开始尝试连接STMP服务器
                                    while (tryTimes <= GlobalObject.SystemInfo.MailLoginRetry)
                                    {
                                        //检查系统及数据库连接状态
                                        if (!CanContinue(conn)) goto EndOfSMTPProcess;
                                        //连接SMTP服务器
                                        if (m_Sender.Connect(mailServer))
                                        {
                                            //连接成功
                                            break;
                                        }
                                        else
                                        {
                                            //连接SMTP服务器失败
                                            //小于尝试次数则延迟后再尝试连接
                                            if (tryTimes < GlobalObject.SystemInfo.MailLoginRetry)
                                            {
                                                try
                                                {
                                                    System.Threading.Thread.Sleep(GlobalObject.SystemInfo.MailLoginRetryTimeout * 1000);
                                                }
                                                catch { }
                                            }
                                            else
                                            {
                                                GlobalObject.WriteOperationLog("E84000001", null,
                                                    mailServer.MailSMTPServerAddr,
                                                    mailServer.MailServerUser);
                                            }
                                        }
                                        tryTimes++;
                                    }

                                    if (tryTimes <= GlobalObject.SystemInfo.MailLoginRetry && m_Sender.SMTPClient.Connected)
                                    {
                                        for (int i = 0; i < sendMailCount; i++)
                                        {
                                            //检查数据库连接状态
                                            if (!CanContinue(conn)) goto EndOfSMTPProcess;
                                           
                                            //邮件可发送
                                            if (m_Sender.IsNextMailReady())
                                            {
                                                //发送尝试计数
                                                int sendTryTime = 1;
                                                //发送邮件处理
                                                while (sendTryTime <= GlobalObject.SystemInfo.MailOperationRetry)
                                                {
                                                    //检查系统及数据库连接状态
                                                    if (!CanContinue(conn)) goto EndOfSMTPProcess;
                                                    //开始发送邮件
                                                    if (m_Sender.SendNextMail())
                                                    {
                                                        //发送成功
                                                        break;
                                                    }
                                                    else
                                                    {
                                                        //发送邮件失败
                                                        //小于尝试次数则延迟后再尝试发送邮件
                                                        if (sendTryTime < GlobalObject.SystemInfo.MailOperationRetry)
                                                        {
                                                            try
                                                            {
                                                                System.Threading.Thread.Sleep(GlobalObject.SystemInfo.MailOperationRetryTimeout * 1000);
                                                            }
                                                            catch { }
                                                        }
                                                        else
                                                        {
                                                            GlobalObject.WriteOperationLog("E84000002", null,
                                                                mailServer.MailSMTPServerAddr,
                                                                mailServer.MailServerUser,
                                                                i + 1);
                                                        }
                                                    }
                                                    sendTryTime++;
                                                }
                                                //设置发送结果为成功或失败
                                                m_Sender.SendMailResult(conn, sendTryTime <= GlobalObject.SystemInfo.MailOperationRetry ? MailTransfer.MailSender.SendStatus.Success : MailTransfer.MailSender.SendStatus.Fauiled);
                                                //SMTP服务连接未成功，则记录日志
                                                if (!m_Sender.SMTPClient.Connected)
                                                {
                                                    GlobalObject.WriteOperationLog("E84000003", null,
                                                           mailServer.MailSMTPServerAddr,
                                                           mailServer.MailServerUser,
                                                           m_Sender.SMTPClient.Response);
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                //设置邮件发送结果为需要重新创建
                                                m_Sender.SendMailResult(conn, MailTransfer.MailSender.SendStatus.ReCreate);
                                            }
                                        }

                                        mailAllSend &= (m_Sender.GetMailCount(mailServer) == 0);
                                    }

                                    //终止
                                EndOfSMTPProcess:
                                    m_Sender.Disconnect();

                                }
                                //关闭数据库连接
                                GlobalObject.CloseConnect(conn);
                            }

                        }
                        break;
                    case ServiceState.Paused: //暂停
                        break;


                }


                //指定当前线程等待相应时间
                if (GlobalObject.State != ServiceState.Stopped)
                {
                    try
                    {
                        if (mailAllSend)
                        {
                            Thread.Sleep(GlobalObject.SystemInfo.MailCheckInterval * 1000);
                        }
                        else
                        {
                            Thread.Sleep(GlobalObject.SystemInfo.MailTransferInterval * 1000);
                        }
                    }
                    catch { }
                }


            }
        }

        /// <summary>
        /// 检查系统状态以及数据库连接状态
        /// </summary>
        /// <param name="conn">数据库连接</param>
        /// <returns>返回是否可继续</returns>
        private bool CanContinue(SqlConnection conn)
        {
            return GlobalObject.State == ServiceState.Running && conn.State != System.Data.ConnectionState.Closed;
        }

        /// <summary>
        /// 线程对象执行状态
        /// </summary>
        public System.Threading.ThreadState State
        {
            get
            {
                return m_Thread.ThreadState;
            }
        }

        #region IDisposable 成员
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            //1、清理线程
            m_Thread = null;

        }

        #endregion
    }
}
